using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Xml.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using JTLeigh.Tools.Development.CopySourceAsHtml.Properties;

namespace JTLeigh.Tools.Development.CopySourceAsHtml.UnitTests
{

    /// <summary>
    /// Unit tests for the <see cref="HtmlStyle"/> class.
    /// </summary>
    [TestClass]
    public class HtmlStyleFixture
    {
        #region Methods

        #region Length

        /// <summary>
        /// Ensures <see cref="HtmlStyle.Length"/> returns the length of the style's string 
        /// representation.
        /// </summary>
        [TestMethod]
        public void TestLength()
        {
            HtmlStyle style;

            style = new HtmlStyle();
            
            Assert.AreEqual(0, style.Length);
            
            style.Append("color: black;");
            
            Assert.AreEqual(13, style.Length);
        }

        #endregion // Length

        #region Append

        /// <summary>
        /// Ensures <see cref="HtmlStyle.Append"/> correctly throws <see cref="ArgumentNullException"/>
        /// when called with a <see langword="null"/> value.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestAppendWithNullValue()
        {
            HtmlStyle style;

            style = new HtmlStyle();
            style.Append(null);
        }

        /// <summary>
        /// Ensures <see cref="HtmlStyle.Append"/> appends style elements separated by spaces and
        /// trims their leading and trailing whitespace.
        /// </summary>
        [TestMethod]
        public void TestAppend()
        {
            HtmlStyle style;

            style = new HtmlStyle();
            style.Append(" color: black; ");
            style.Append(" background: white; ");
            
            Assert.AreEqual("color: black; background: white;", style.ToString());
        }

        #endregion // Append

        #region AppendFormat

        /// <summary>
        /// Ensures <see cref="HtmlStyle.AppendFormat"/> correctly throws <see cref="ArgumentNullException"/>
        /// when called with a <see langword="null"/> format.
        /// </summary>
        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestAppendFormatWithNullFormat()
        {
            HtmlStyle style;

            style = new HtmlStyle();
            style.AppendFormat(null);
        }

        /// <summary>
        /// Ensures <see cref="HtmlStyle.Append"/> formats style elements, appends them separated 
        /// by spaces, and trims their leading and trailing whitespace.
        /// </summary>
        [TestMethod]
        public void TestAppendFormat()
        {
            HtmlStyle style;

            style = new HtmlStyle();
            style.AppendFormat(" font-family: {0}; ", "Courier New");
            style.AppendFormat(" font-size: {0}pt; ", 12);
            
            Assert.AreEqual("font-family: Courier New; font-size: 12pt;", style.ToString());
        }

        #endregion // AppendFormat

        #region Equals

        /// <summary>
        /// Ensures <see cref="HtmlStyle.Equals"/> returns <see langword="false"/> when called with
        /// a <see langword="null"/> value.
        /// </summary>
        [TestMethod]
        public void TestEqualsWithNullValue()
        {
            HtmlStyle style;

            style = new HtmlStyle();
            style.Append("color: black;");
            style.Append("background: white;");

            Assert.IsFalse(style.Equals(null));
        }

        /// <summary>
        /// Ensures <see cref="HtmlStyle.Equals"/> returns <see langword="false"/> when called with
        /// a different value.
        /// </summary>
        [TestMethod]
        public void TestEqualsWithDifferentValue()
        {
            HtmlStyle style1;
            HtmlStyle style2;

            style1 = new HtmlStyle();
            style1.Append("color: black;");
            style1.Append("background: white;");

            style2 = new HtmlStyle();
            style2.Append("color: white;");
            style2.Append("background: black;");

            Assert.IsFalse(style1.Equals(style2));
        }

        /// <summary>
        /// Ensures <see cref="HtmlStyle.Equals"/> returns <see langword="true"/> when called with
        /// the same value.
        /// </summary>
        [TestMethod]
        public void TestEqualsWithSameValue()
        {
            HtmlStyle style1;
            HtmlStyle style2;

            style1 = new HtmlStyle();
            style1.Append("color: black;");
            style1.Append("background: white;");

            style2 = new HtmlStyle();
            style2.Append("color: black;");
            style2.Append("background: white;");

            Assert.IsTrue(style1.Equals(style2));
        }

        #endregion // Equals

        #region Serialization

        /// <summary>
        /// Ensures <see cref="ColorableItemStyle"/> can be serialized to and deserialized from
        /// XML with no loss of data.
        /// </summary>
        [TestMethod]
        public void TestSerializeDeserialize()
        {
            XmlSerializer serializer;
            MemoryStream stream;
            HtmlStyle originalStyle;
            HtmlStyle  copiedStyle;

            serializer = new XmlSerializer(typeof(HtmlStyle));
            stream = new MemoryStream();

            originalStyle = new HtmlStyle();
            originalStyle.Append("margin: 0px;");

            serializer.Serialize(Console.Out, originalStyle);
            serializer.Serialize(stream, originalStyle);
            stream.Position = 0;
            copiedStyle = (HtmlStyle)serializer.Deserialize(stream);

            Assert.AreEqual(originalStyle.ToString(), copiedStyle.ToString());
        }

        #endregion // 

        #endregion // Methods
    }

}
